package com.win.oauth.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class JWTUtils {

    private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000; //过期
    private static final String SECRET = "super winner";
    private static final String USER_CLAIM_KEY = "userId";
    private static final String ROLES_CLAIM_KEY = "roleIds";
    private static final String IS_ADMIN_CLAIM_KEY = "isAdmin";

    public static String sign(Long userId, List<Long> roleIds, boolean isAdmin) {
        Date exp = new Date(System.currentTimeMillis() + EXPIRE_TIME); //过期时间
        return sign(userId, roleIds, isAdmin, exp);
    }

    public static String sign(Long userId, List<Long> roleIds, boolean isAdmin, Date exp) {
        Date isa = new Date(); //签发时间
        Algorithm algorithm = Algorithm.HMAC256(SECRET); //设置头信息
        HashMap<String, Object> header = new HashMap<>(2);
        header.put("typ", "JWT");
        header.put("alg", "HS256"); //附带username和userID生成签名
        return JWT.create().withHeader(header)
                .withClaim(USER_CLAIM_KEY, userId)
                .withArrayClaim(ROLES_CLAIM_KEY, roleIds.toArray(new Long[0]))
                .withClaim(IS_ADMIN_CLAIM_KEY, isAdmin)
                .withIssuedAt(isa)
                .withExpiresAt(exp).sign(algorithm);
    }

    //校验token
    public static UserClaims verity(String token) {
        try {

            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);

            Long userId = jwt.getClaim(USER_CLAIM_KEY).asLong();
            List<Long> roleIds = jwt.getClaim(ROLES_CLAIM_KEY).asList(Long.class);
            Boolean isAdmin = jwt.getClaim(IS_ADMIN_CLAIM_KEY).asBoolean();
            Date isa = jwt.getIssuedAt();
            Date exp = jwt.getExpiresAt();

            UserClaims claims = new UserClaims();
            claims.setUserId(userId);
            claims.setRoleIds(roleIds);
            claims.setIsAdmin(isAdmin);
            claims.setIssuedAt(isa);
            claims.setExpiresAt(exp);
            return claims;
        } catch (IllegalArgumentException | JWTVerificationException e) {
            return null;
        }
    }

    public static void main(String[] args) {
        String sign = JWTUtils.sign(10L, Arrays.asList(1L, 2L), true);
        UserClaims userClaims = JWTUtils.verity(sign);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        assert userClaims != null;
        System.err.println(sdf.format(userClaims.getIssuedAt()));
        System.err.println(sdf.format(userClaims.getExpiresAt()));
        System.err.println(userClaims.getUserId());
        System.err.println(userClaims.isAdmin());
    }

}
